import java.awt.Component;
import java.awt.Graphics;
import java.awt.GraphicsEnvironment;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class VsyncDemo
{
	public static void main(String[] args) {
		SyncWindow syncWindow = new SyncWindow();
		syncWindow.setVisible(true);
		vsync(syncWindow.getContentPane(), SyncWindow.LOCK);
	}
	
	private static class SyncWindow extends JFrame
	{
		/**
		 * 
		 */
		private static final long serialVersionUID = 7771603407183091173L;

		private static final Object LOCK = new Object();
		
		int dotX = 0;
		
		public SyncWindow() {
			setSize(1000, 750);
			setLocationRelativeTo(null);
			JPanel contentPane = new JPanel() {
				/**
				 * 
				 */
				private static final long serialVersionUID = -7825450540970085792L;

				@Override
				protected void paintComponent(Graphics g) {
					super.paintComponent(g);
					synchronized(LOCK) {
						if(dotX >= getWidth()) {
							dotX = 0;
						}else {
							dotX+=2;
						}
					}
					g.drawRoundRect(dotX, getHeight() / 2, 25, 25, 5, 5);
				}
			};
			setContentPane(contentPane);
		}
	}
	
	private static void vsync(Component comp, Object lock) {
		int refreshRate = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode().getRefreshRate();
		long paintGap = 1000 / refreshRate;
		new Thread(new Runnable() {
			@Override
			public void run() {
				while(true) {
					comp.repaint();
					
					synchronized (lock) {
						try {
							Thread.sleep(paintGap);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
			}
		}).start();
	}
}
